package com.funtest.mockito.practise

import org.apache.http.client.methods.HttpRequestBase
import org.apache.logging.log4j.LogManager
import org.apache.logging.log4j.Logger
import spock.lang.Shared
import spock.lang.Specification

import static org.mockito.Mockito.*

class Demo extends Specification {

    @Shared
    private static final Logger logger = LogManager.getLogger(Demo.class);

    @Shared
    List listsss = org.mockito.Mockito.mock(List)

    @Shared
    HttpRequestBase httpRequestBase = org.mockito.Mockito.mock(HttpRequestBase.class)

    def setup() {
        logger.info("测试方法开始了")
    }

    def cleanup() {
        logger.info("测试方法结束了")
    }

    def setupSpec() {
        logger.info("测试类[${getClass().getName()}]开始了")
    }

    def cleanupSpec() {
        logger.info("测试类[${getClass().getName()}]结束了")
    }

    def "这是一个普通的demo"() {
        given: "创建一个存根list,添加一些元素"
        List mockedList = org.mockito.Mockito.mock(List.class);
        mockedList.add("one");
        mockedList.add("two");
        mockedList.add("three times");
        mockedList.add("three times");
        mockedList.add("three times");
        org.mockito.Mockito.when(mockedList.size()).thenReturn(5);
        mockedList.add("3")
        mockedList.add("3")
        mockedList.add("3")
        mockedList.add("3")

        expect: "验证属性以及方法调用次数"
        5 == mockedList.size()
        false == org.mockito.Mockito.verify(mockedList, org.mockito.Mockito.atLeastOnce()).add("one")
        false == org.mockito.Mockito.verify(mockedList, org.mockito.Mockito.times(3)).add("three times")
        false == org.mockito.Mockito.verify(mockedList, org.mockito.Mockito.atMost(4)).add("3")
        false == org.mockito.Mockito.verify(mockedList, org.mockito.Mockito.never()).add("30")
    }

    def "这是一个测试的mockito模拟方法返回"() {
        given: "虚拟一个迭代器对象"
        def iterator = org.mockito.Mockito.mock(Iterator.class)
        org.mockito.Mockito.when(iterator.next()).thenReturn("hello").thenReturn("world")

        expect: "测试迭代器元素拼接"
        "hello world" == iterator.next() + com.funtester.config.Constant.SPACE_1 + iterator.next()
    }

    def "这是一个测试,用来在对象初始化之后mock对象的"() {
        given: "创建对象后再Mockito"
        def iterator = new ArrayList()
        iterator.add("323")
        def list = org.mockito.Mockito.spy(iterator)
        org.mockito.Mockito.doReturn("fun").when(list).get(3)
        org.mockito.Mockito.doReturn(3).when(list).get(0)

        expect:
        list.contains("323")
        "fun" == list.get(3)
        3 == list.get(0)
    }

    def "这是一个测试,抛出异常的测试用例"() {
        given: "创建测试对象"
        def object = org.mockito.Mockito.mock(ArrayList.class)
        org.mockito.Mockito.when(object.get(1)).thenThrow(new IndexOutOfBoundsException("我是测试")) //只能抛出可能的抛出的异常
        def re = 0
        try {
            object.get(1)
        } catch (IndexOutOfBoundsException e) {
            re = 1
        }

        expect:
        re == 1
    }

    def "这是一个测试方法返回值的用例"() {
        given:
        def j = org.mockito.Mockito.mock(DemoJ.class)
        org.mockito.Mockito.doAnswer(org.mockito.AdditionalAnswers.returnsFirstArg()).when(j).ds(org.mockito.ArgumentMatchers.anyInt(), org.mockito.ArgumentMatchers.anyInt())

        //        when(list.add(anyString())).thenAnswer(returnsFirstArg());
        // with then() alias:
        //        when(list.add(anyString())).then(returnsFirstArg());
        expect:
        3 == j.ds(3, 32)

    }

    def "我是测试共享Mock对象的用例"() {
        given:

        org.mockito.Mockito.when(listsss.get(org.mockito.ArgumentMatchers.anyInt())).thenReturn(3)

        expect:
        3 == listsss.get(3)
    }

    /**
     *      对于未指定mock的方法，spy默认会调用真实的方法，有返回值的返回真实的返回值，而mock默认不执行，有返回值的，默认返回null
     */
    def "spy和mock区别"() {
        given:
        def list = [1, 2, 3, 4]
        def integers = org.mockito.Mockito.spy(list)
        org.mockito.Mockito.when(integers.size()).thenReturn(9)

        expect:
        integers.size() == 9
        integers.get(0) == 1

    }
}
